package com.zc.auth.security.core.configuration;

import com.zc.auth.security.core.access.RoleUrlAccessDecisionManager;
import com.zc.auth.security.core.access.meta.DefaultUrlRoleMetaDataManager;
import com.zc.auth.security.core.access.meta.UrlInvocationSecurityMetadataSource;
import com.zc.auth.security.core.access.meta.UrlRoleMetaDataManager;
import com.zc.auth.security.core.configuration.adapter.WebAuthSecurityConfigurerAdapter;
import com.zc.auth.security.core.handler.RoleAccessDeniedHandler;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.access.AccessDecisionManager;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.access.AccessDeniedHandler;

import javax.annotation.PostConstruct;
import java.util.Collection;
import java.util.Map;

/**
 * 基于Servlet处理的配置
 *
 * @author zcj
 * @version 1.0.0
 * @date 2022/1/12 10:43
 */
@Configuration(proxyBeanMethods = false)
@ConditionalOnMissingBean({WebSecurityConfigurerAdapter.class})
@ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.SERVLET)
@EnableWebSecurity
@Slf4j
public class ServletSecurityConfiguration {

    @Autowired
    private UrlRoleMetaDataManager urlRoleMetaDataManager;

    @Bean
    @ConditionalOnMissingBean(value = UrlInvocationSecurityMetadataSource.class)
    public UrlInvocationSecurityMetadataSource urlInvocationSecurityMetadataSource() {
        return new UrlInvocationSecurityMetadataSource(urlRoleMetaDataManager);
    }

    @Bean
    @ConditionalOnMissingBean(value = AccessDecisionManager.class)
    public AccessDecisionManager accessDecisionManager() {
        return new RoleUrlAccessDecisionManager();
    }

    @Bean
    @ConditionalOnMissingBean(value = AccessDeniedHandler.class)
    public AccessDeniedHandler accessDeniedHandler() {
        return new RoleAccessDeniedHandler();
    }


    @Bean
    @ConditionalOnMissingBean(value = {WebAuthSecurityConfigurerAdapter.class, WebSecurityConfigurerAdapter.class})
    public WebSecurityConfigurerAdapter webSecurityConfigurerAdapter() {
        return new WebAuthSecurityConfigurerAdapter();
    }

    @PostConstruct
    public void initMetaData() {
        if (this.urlRoleMetaDataManager instanceof DefaultUrlRoleMetaDataManager) {
            Map<String, ? extends Collection<String>> map = this.urlRoleMetaDataManager.updateUrlsAndRolesMap();
            log.info(String.format("角色url权限元数据加载完成，共%s条", map == null ? 0 : map.size()));
        }
    }

    @PostConstruct
    public void initContextHolderStrategyName() {
        System.setProperty(SecurityContextHolder.SYSTEM_PROPERTY, SecurityContextHolder.MODE_INHERITABLETHREADLOCAL);
    }


}
